package com.atguigu.tingshu.search.service.impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.Suggestion;
import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.album.client.AlbumInfoFeignClient;
import com.atguigu.tingshu.album.client.CategoryFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.PinYinUtils;
import com.atguigu.tingshu.model.album.*;
import com.atguigu.tingshu.model.search.AlbumInfoIndex;
import com.atguigu.tingshu.model.search.AttributeValueIndex;
import com.atguigu.tingshu.model.search.SuggestIndex;
import com.atguigu.tingshu.query.search.AlbumIndexQuery;
import com.atguigu.tingshu.search.repository.AlbumIndexRepository;
import com.atguigu.tingshu.search.repository.SuggestIndexRepository;
import com.atguigu.tingshu.search.service.SearchService;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.search.AlbumInfoIndexVo;
import com.atguigu.tingshu.vo.search.AlbumSearchResponseVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.suggest.Completion;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;


@Slf4j
@Service
@SuppressWarnings({"all"})
public class SearchServiceImpl implements SearchService {


    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private AlbumInfoFeignClient albumInfoFeignClient;

    @Autowired
    private CategoryFeignClient categoryFeignClient;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    @Autowired
    private AlbumIndexRepository albumIndexRepository;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private ElasticsearchClient elasticsearchClient;

    @Autowired
    private SuggestIndexRepository suggestIndexRepository;

    @Autowired
    private RedisTemplate redisTemplate;


    @Override
    public void upperAlbum(Long albumId) {
        //  创建对象
        AlbumInfoIndex albumInfoIndex = new AlbumInfoIndex();
        //  赋值：
        //  获取专辑对象
        CompletableFuture<AlbumInfo> albumInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
            Result<AlbumInfo> albumInfoResult = albumInfoFeignClient.getAlbumInfo(albumId);
            //  判断这个返回结果集不为空.
            Assert.notNull(albumInfoResult, "返回专辑结果集为空");
            //  从结果集中获取数据
            AlbumInfo albumInfo = albumInfoResult.getData();
            Assert.notNull(albumInfo, "返回专辑为空");
            //  属性拷贝
            BeanUtils.copyProperties(albumInfo, albumInfoIndex);
            return albumInfo;
        }, threadPoolExecutor);


        //  远程调用获取三级分类对象 拉姆达表达式：复制小括号{如果是一个参数，小括号可以省略.}，写死右箭头，落地大括号{里面方法体 ，如果直接返回数据，大括号可以省略}.
        CompletableFuture<Void> categoryCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            Result<BaseCategoryView> categoryViewResult = this.categoryFeignClient.getCategoryView(albumInfo.getCategory3Id());
            Assert.notNull(categoryViewResult, "返回分类结果集为空");
            BaseCategoryView categoryView = categoryViewResult.getData();
            Assert.notNull(categoryView, "返回分类为空");
            //  赋值数据：
            albumInfoIndex.setCategory1Id(categoryView.getCategory1Id());
            albumInfoIndex.setCategory2Id(categoryView.getCategory2Id());
        }, threadPoolExecutor);

        //  三级分类Id 不需要赋值. BeanUtils.copyProperties(albumInfo,albumInfoIndex);已经赋值过了。
        //  查询统计信息。根据专辑Id 查询 album_stat.stat_type; stat_num
        int playStatNum = new Random().nextInt(1000000000);
        int commentStatNum = new Random().nextInt(10000000);
        int subscribeStatNum = new Random().nextInt(100000);
        int buyStatNum = new Random().nextInt(1000000);
        albumInfoIndex.setPlayStatNum(playStatNum);
        albumInfoIndex.setCommentStatNum(commentStatNum);
        albumInfoIndex.setSubscribeStatNum(subscribeStatNum);
        albumInfoIndex.setBuyStatNum(buyStatNum);
        int hotScore = new Random().nextInt(10000);
        albumInfoIndex.setHotScore((double) hotScore);

        //  赋值属性数据： 属性数据类型 Nested。
        //  远程调用 attributeId valueId
        CompletableFuture<Void> attrCompletableFuture = CompletableFuture.runAsync(() -> {
            Result<List<AlbumAttributeValue>> albumAttributeValueResult = albumInfoFeignClient.findAlbumAttributeValue(albumId);
            Assert.notNull(albumAttributeValueResult, "专辑属性结果集为空");
            List<AlbumAttributeValue> albumAttributeValueList = albumAttributeValueResult.getData();
            Assert.notNull(albumAttributeValueList, "专辑属性集合为空");
            List<AttributeValueIndex> attributeValueIndexList = albumAttributeValueList.stream().map(albumAttributeValue -> {
                //  创建对象
                AttributeValueIndex attributeValueIndex = new AttributeValueIndex();
                BeanUtils.copyProperties(albumAttributeValue, attributeValueIndex);
                return attributeValueIndex;
            }).collect(Collectors.toList());
            //  赋值
            albumInfoIndex.setAttributeValueIndexList(attributeValueIndexList);
        }, threadPoolExecutor);

        //  主播：
        CompletableFuture<Void> userCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            Result<UserInfoVo> userInfoVoResult = this.userInfoFeignClient.getUserInfoVo(albumInfo.getUserId());
            Assert.notNull(userInfoVoResult, "用户结果集为空");
            UserInfoVo userInfoVo = userInfoVoResult.getData();
            Assert.notNull(userInfoVo, "用户对象为空");
            albumInfoIndex.setAnnouncerName(userInfoVo.getNickname());
        }, threadPoolExecutor);

        //  将四个线程进行组合：
        CompletableFuture.allOf(
                categoryCompletableFuture,
                attrCompletableFuture,
                userCompletableFuture,
                albumInfoCompletableFuture
        ).join();

        //  保存：必须使用api 操作！
        albumIndexRepository.save(albumInfoIndex);

        //  将部分数据保存到提词库中.
        SuggestIndex suggestIndex = new SuggestIndex();
        //  赋值：id 赋值能否重复? --- keyword;
        suggestIndex.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        suggestIndex.setTitle(albumInfoIndex.getAlbumTitle());
        //  三国
        suggestIndex.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumTitle()}));
        //  sanguo
        suggestIndex.setKeywordPinyin(new Completion(new String[]{PinYinUtils.toHanyuPinyin(albumInfoIndex.getAlbumTitle())}));
        //  sg
        suggestIndex.setKeywordSequence(new Completion(new String[]{PinYinUtils.getFirstLetter(albumInfoIndex.getAlbumTitle())}));
        suggestIndexRepository.save(suggestIndex);

        //  简介也保存到提出库.
        SuggestIndex suggestIndexAlbumIntro = new SuggestIndex();
        //  赋值：id 赋值能否重复? --- intro;
        suggestIndexAlbumIntro.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        suggestIndexAlbumIntro.setTitle(albumInfoIndex.getAlbumIntro());
        suggestIndexAlbumIntro.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumIntro()}));
        suggestIndexAlbumIntro.setKeywordPinyin(new Completion(new String[]{PinYinUtils.toHanyuPinyin(albumInfoIndex.getAlbumIntro())}));
        suggestIndexAlbumIntro.setKeywordSequence(new Completion(new String[]{PinYinUtils.getFirstLetter(albumInfoIndex.getAlbumIntro())}));
        suggestIndexRepository.save(suggestIndexAlbumIntro);

        //  保存专辑Id 到布隆过滤器
        RBloomFilter<Object> bloomFilter = this.redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
        bloomFilter.add(albumId);
    }

    @Override
    public List<AlbumInfoIndex> findRankingList(Long category1Id, String dimension) {
        //  hget key field;
        return (List<AlbumInfoIndex>) this.redisTemplate.opsForHash().get(RedisConstant.RANKING_KEY_PREFIX + category1Id, dimension);
    }

    @Override
    public void updateLatelyAlbumRanking() {
        //  先获取所有一级分类Id 数据
        Result<List<BaseCategory1>> baseCategory1Result = categoryFeignClient.findAllCategory1();
        Assert.notNull(baseCategory1Result, "一级分类结果集为空");
        // 获取data数据
        List<BaseCategory1> category1List = baseCategory1Result.getData();
        // 判断集合
        Assert.notNull(category1List, "一级分类集合为空");
        //  存储到缓存：hset key field value;
        for (BaseCategory1 baseCategory1 : category1List) {
            //  声明记录五个维度的数组。
            String[] rankingDimensionArray = new String[]{"hotScore", "playStatNum", "subscribeStatNum", "buyStatNum", "commentStatNum"};
            //  循环遍历
            for (String rankingDimension : rankingDimensionArray) {
                //  获取es中的排序数据
                SearchResponse<AlbumInfoIndex> searchResponse = null;
                try {
                    searchResponse = elasticsearchClient.search(s -> s.index("albuminfo")
                                    .query(q -> q.term(t -> t.field("category1Id").value(baseCategory1.getId())))
                                    .sort(st -> st.field(f -> f.field(rankingDimension).order(SortOrder.Desc)))
                                    .size(10)
                            ,
                            AlbumInfoIndex.class);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                //  获取数据
                List<AlbumInfoIndex> albumInfoIndexList = searchResponse.hits().hits().stream().map(Hit::source).collect(Collectors.toList());
                //  hset key field value;
                this.redisTemplate.opsForHash().put(RedisConstant.RANKING_KEY_PREFIX + baseCategory1.getId(), rankingDimension, albumInfoIndexList);
            }
        }
    }

    @Override
    public List<String> completeSuggest(String keyword) {
        //  查询数据：
        SearchResponse<SuggestIndex> response = null;
        try {
            response = elasticsearchClient.search(f -> f.index("suggestinfo")
                            .suggest(s -> s.suggesters("suggestionKeyword", s1 -> s1.prefix(keyword)
                                                    .completion(c -> c.field("keyword").skipDuplicates(true)
                                                            .size(10).fuzzy(z -> z.fuzziness("auto")))
                                            )
                                            .suggesters("suggestionkeywordPinyin", s2 -> s2.prefix(keyword)
                                                    .completion(c -> c.field("keywordPinyin").skipDuplicates(true)
                                                            .size(10).fuzzy(z -> z.fuzziness("auto")))
                                            )
                                            .suggesters("suggestionkeywordSequence", s2 -> s2.prefix(keyword)
                                                    .completion(c -> c.field("keywordSequence").skipDuplicates(true)
                                                            .size(10).fuzzy(z -> z.fuzziness("auto")))
                                            )
                            )
                    ,
                    SuggestIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        //  获取数据：
        List<String> keywordList = new ArrayList<>();
        keywordList.addAll(this.getSuggestResult(response, "suggestionKeyword"));
        keywordList.addAll(this.getSuggestResult(response, "suggestionkeywordPinyin"));
        keywordList.addAll(this.getSuggestResult(response, "suggestionkeywordSequence"));
        //  三个集合数据添加到一个集合中
        //  判断这个集合的长度，如果不够10条数据， 如何获取集合的长度
        if (keywordList.size() < 10) {
            //  执行dsl 语句.
            SearchResponse<SuggestIndex> searchResponse = null;
            try {
                searchResponse = elasticsearchClient.search(s -> s.index("suggestinfo").query(q -> q.match(m -> m.field("title").query(keyword))), SuggestIndex.class);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            //  List<String> list = searchResponse.hits().hits().stream().map(hit -> hit.source().getTitle()).collect(Collectors.toList());
            for (Hit<SuggestIndex> hit : searchResponse.hits().hits()) {
                String title = hit.source().getTitle();
                keywordList.add(title);
                if (keywordList.size() >= 10) {
                    break;
                }
            }
        }
        //  返回集合数据
        return keywordList;
    }

    private List<String> getSuggestResult(SearchResponse<SuggestIndex> response, String keyword) {
        //  声明一个集合
        List<String> list = new ArrayList<>();
        //  根据key 获取数据.
        List<Suggestion<SuggestIndex>> suggestionList = response.suggest().get(keyword);
        //  判断
        for (Suggestion<SuggestIndex> suggestIndexSuggestion : suggestionList) {
            list = suggestIndexSuggestion.completion().options().stream().map(suggestIndexCompletionOption -> {
                //  获取title数据
                return suggestIndexCompletionOption.source().getTitle();
            }).collect(Collectors.toList());
        }
        //  返回数据
        return list;
    }


    @Override
    public List<Map<String, Object>> channel(Long category1Id) {
        //  先根据一级分类Id 找到三级分类对象数据.
        Result<List<BaseCategory3>> baseCategory3ListResult = categoryFeignClient.findTopBaseCategory3(category1Id);
        Assert.notNull(baseCategory3ListResult, "三级分类结果集为空");
        List<BaseCategory3> baseCategory3List = baseCategory3ListResult.getData();
        //  将 baseCategory3List 集合变为map 集合,key=category3Id,value=BaseCategory3;
        Map<Long, BaseCategory3> category3Map = baseCategory3List.stream().collect(Collectors.toMap(BaseCategory3::getId, baseCategory3 -> baseCategory3));

        Assert.notNull(baseCategory3List, "三级分类集合为空");
        //  后续会获取到三级分类集合中的Id列表。
        List<Long> baseCategory3IdList = baseCategory3List.stream().map(BaseCategory3::getId).collect(Collectors.toList());
        //  生成 dsl 语句.ts.value() List<FieldValue> list 这个对象应该是三级分类Id 集合.
        //  需要将 baseCategory3IdList 转换为 List<FieldValue> list
        List<FieldValue> list = baseCategory3IdList.stream().map(baseCategory3Id -> FieldValue.of(baseCategory3Id)).collect(Collectors.toList());
        SearchResponse<AlbumInfoIndex> searchResponse = null;
        try {
            searchResponse = elasticsearchClient.search(f -> f.index("albuminfo").query(q -> q.terms(t -> t.field("category3Id").terms(ts -> ts.value(list))))
                            .aggregations("groupByCategory3IdAgg", a -> a.terms(t -> t.field("category3Id"))
                                    .aggregations("topSixHotScoreAgg", ag -> ag.topHits(ft -> ft.size(6)
                                            .sort(s -> s.field(fn -> fn.field("buyStatNum").order(SortOrder.Desc)))))
                            )
                    ,
                    AlbumInfoIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //  获取到结果集。
        Map<String, Aggregate> aggregations = searchResponse.aggregations();
        Aggregate groupByCategory3IdAgg = aggregations.get("groupByCategory3IdAgg");
        List<Map<String, Object>> mapList = groupByCategory3IdAgg.lterms().buckets().array().stream().map(bucket -> {
            //  声明一个集合对象
            Map<String, Object> map = new HashMap<>();
            //  获取三级分类Id
            long category3Id = bucket.key();
            //  获取三级分类Id下的专辑数据集合
            List<AlbumInfoIndex> albumInfoIndexList = bucket.aggregations().get("topSixHotScoreAgg").topHits().hits().hits().stream().map(hit -> {
                String strJson = hit.source().toString();
                AlbumInfoIndex albumInfoIndex = JSON.parseObject(strJson, AlbumInfoIndex.class);
                return albumInfoIndex;
            }).collect(Collectors.toList());
            //  存储三级分类对象
            map.put("baseCategory3", category3Map.get(category3Id));
            //  存储专辑集合
            map.put("list", albumInfoIndexList);
            return map;
        }).collect(Collectors.toList());
        //  返回数据
        return mapList;
    }

    /**
     * 查询方法。
     *
     * @param albumIndexQuery 承载着用户输入的各种检索条件
     * @return
     */
    @Override
    public AlbumSearchResponseVo search(AlbumIndexQuery albumIndexQuery) {
        //  返回这个对象的本质：给 AlbumSearchResponseVo 对象赋值：
        /*
            private List<AlbumInfoIndexVo> list = new ArrayList<>(); 专辑列表；根据用户输入的检索条件，生成dsl语句。获取结果集.
            private Long total;//总记录数
            private Integer pageSize;//每页显示的内容
            private Integer pageNo;//当前页面
            private Long totalPages;
         */
        //  获取 一个 SearchRequest 对象.
        SearchRequest searchRequest = this.queryBuildDsl(albumIndexQuery);
        //  调用api
        SearchResponse<AlbumInfoIndex> searchResponse = null;
        try {
            searchResponse = elasticsearchClient.search(searchRequest, AlbumInfoIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //  定义一个方法给albumSearchResponseVo 赋值：list total
        AlbumSearchResponseVo albumSearchResponseVo = this.parseResultData(searchResponse);
        //  赋值：
        //  private Integer pageSize;//每页显示的内容
        //  private Integer pageNo;//当前页面
        //  private Long totalPages;
        //  默认第一页
        albumSearchResponseVo.setPageNo(albumIndexQuery.getPageNo());
        //  默认每页显示20条
        albumSearchResponseVo.setPageSize(albumIndexQuery.getPageSize());
        //  总页数 10 3 4 | 9 3 3
        //  Long totalPages = albumSearchResponseVo.getTotal() % albumIndexQuery.getPageSize() == 0 ? albumSearchResponseVo.getTotal() / albumIndexQuery.getPageSize() : albumSearchResponseVo.getTotal() / albumIndexQuery.getPageSize() + 1;
        Long totalPages = (albumSearchResponseVo.getTotal() + albumIndexQuery.getPageSize() - 1) / albumIndexQuery.getPageSize();
        albumSearchResponseVo.setTotalPages(totalPages);
        //  返回数据
        return albumSearchResponseVo;
    }

    /**
     * 获取返回结果集
     *
     * @param searchResponse
     * @return
     */
    private AlbumSearchResponseVo parseResultData(SearchResponse<AlbumInfoIndex> searchResponse) {
        //  声明对象
        AlbumSearchResponseVo albumSearchResponseVo = new AlbumSearchResponseVo();
        //  AlbumSearchResponseVo 给属性赋值;
        //  private List<AlbumInfoIndexVo> list = new ArrayList<>();

        List<Hit<AlbumInfoIndex>> hitList = searchResponse.hits().hits();
        //  循环遍历.
        List<AlbumInfoIndexVo> albumInfoIndexList = hitList.stream().map(hit -> {
            //  创建对象
            AlbumInfoIndexVo albumInfoIndexVo = new AlbumInfoIndexVo();
            AlbumInfoIndex albumInfoIndex = hit.source();
            //  属性拷贝：
            BeanUtils.copyProperties(albumInfoIndex, albumInfoIndexVo);
            //  判断是否通过关键词查询;
            if (hit.highlight().get("albumTitle") != null) {
                if (StringUtils.isNotBlank(hit.highlight().get("albumTitle").get(0))) {
                    //  取出高亮的 albumTitle
                    albumInfoIndexVo.setAlbumTitle(hit.highlight().get("albumTitle").get(0));
                }
            }
            //  返回数据
            return albumInfoIndexVo;
        }).collect(Collectors.toList());

        //  赋值：
        albumSearchResponseVo.setList(albumInfoIndexList);
        //  赋值总记录数
        albumSearchResponseVo.setTotal(searchResponse.hits().total().value());
        //  返回数据
        return albumSearchResponseVo;
    }

    /**
     * 获取 SearchRequest 对象
     *
     * @param albumIndexQuery
     * @return
     */
    private SearchRequest queryBuildDsl(AlbumIndexQuery albumIndexQuery) {
        //  创建SearchRequest 对象
        SearchRequest.Builder searchRequestBuilder = new SearchRequest.Builder();
        searchRequestBuilder.index("albuminfo");
        //  1.  判断当前用户是通过哪种方式进行检索的！
        //  判断 albumIndexQuery.getKeyword() 不为空,无检索不高亮.
        if (StringUtils.isNotBlank(albumIndexQuery.getKeyword())) {
            //  query--bool--should--match
            searchRequestBuilder.query(q -> q.bool(b -> b.should(s -> s.match(m -> m.field("albumTitle").query(albumIndexQuery.getKeyword())))
                    .should(s -> s.match(m -> m.field("albumIntro").query(albumIndexQuery.getKeyword())))
            ));
            //  设置高亮：
            searchRequestBuilder.highlight(h -> h.fields("albumTitle", hf -> hf.preTags("<span style=color:#f86442>").postTags("</span>")));
        }
        //  判断用户是否根据分类Id 检索
        if (null != albumIndexQuery.getCategory1Id()) {
            //  query-bool-filter-term
            searchRequestBuilder.query(q -> q.bool(b -> b.filter(f -> f.term(t -> t.field("category1Id").value(albumIndexQuery.getCategory1Id())))));
        }
        if (null != albumIndexQuery.getCategory2Id()) {
            //  query-bool-filter-term
            searchRequestBuilder.query(q -> q.bool(b -> b.filter(f -> f.term(t -> t.field("category2Id").value(albumIndexQuery.getCategory2Id())))));
        }
        if (null != albumIndexQuery.getCategory3Id()) {
            //  query-bool-filter-term
            searchRequestBuilder.query(q -> q.bool(b -> b.filter(f -> f.term(t -> t.field("category3Id").value(albumIndexQuery.getCategory3Id())))));
        }

        //  属性数据类型是 nested{能够允许数组彼此独立的检索和查询}.
        List<String> attributeList = albumIndexQuery.getAttributeList();
        //  属性:属性值
        if (!CollectionUtils.isEmpty(attributeList)) {
            //  循环遍历
            for (String attribute : attributeList) {
                //  attribute=属性:属性值
                String[] split = attribute.split(":");
                //  split[0] 属性： split[1] 属性值：
                //  判断
                if (null != split && split.length == 2) {
                    //  query-nested-path-query-bool-filter-term;
                    //  只通过属性与属性值查询！但是，如果有其他查询或过滤条件时，就会失败.
                    //                    searchRequestBuilder.query(
                    //                            q -> q.nested(n -> n.path("attributeValueIndexList")
                    //                                    .query(qy -> qy.bool(b -> b.filter(f -> f.term(t -> t.field("attributeValueIndexList.attributeId").value(split[0])))
                    //                                            .filter(f -> f.term(t -> t.field("attributeValueIndexList.attributeValueId").value(split[1])))
                    //                                    )))
                    //                    );
                    //  多条件查询！
                    searchRequestBuilder.query(q -> q.bool(b -> b.filter(f -> f.nested(n -> n.path("attributeValueIndexList")
                            .query(qy -> qy.bool(bl -> bl.filter(fl -> fl.term(t -> t.field("attributeValueIndexList.attributeId").value(split[0])))
                                    .filter(fl -> fl.term(t -> t.field("attributeValueIndexList.valueId").value(split[1])))
                            ))
                    ))));
                }
            }
        }
        //  排序-分页
        //  先获取排序方式
        //  排序（综合排序[1:desc] 播放量[2:desc] 发布时间[3:desc]；asc:升序 desc:降序）
        String order = albumIndexQuery.getOrder();
        //  判断order是否为空
        if (StringUtils.isNotBlank(order)) {
            //  order=1:desc or 2:desc; 使用:对order 进行分割
            String[] split = order.split(":"); // split[0]=1或2或3 split[1]=desc 或 asc;
            //  判断split 是否为空
            if (null != split && split.length == 2) {
                //  声明一个排序字段
                String orderField = null;
                switch (split[0]) {
                    case "1":
                        orderField = "hotScore";
                        break;
                    case "2":
                        orderField = "playStatNum";
                        break;
                    case "3":
                        orderField = "createTime";
                }
                //  设置排序字段与规则，构建dsl语句.
                String finalOrderField = orderField;
                searchRequestBuilder.sort(s -> s.field(f -> f.field(finalOrderField).order(split[1].equals("asc") ? SortOrder.Asc : SortOrder.Desc)));
            }
        }

        //  设置分页
        Integer from = (albumIndexQuery.getPageNo() - 1) * albumIndexQuery.getPageSize();
        searchRequestBuilder.from(from);
        searchRequestBuilder.size(albumIndexQuery.getPageSize());
        //  searchRequest 主要作用是封装dsl语句.
        //  创建对象
        SearchRequest searchRequest = searchRequestBuilder.build();
        System.out.println("DSL:\t" + searchRequest.toString());
        //  返回对象
        return searchRequest;
    }

    /**
     * 专辑下架
     *
     * @param albumId
     */
    @Override
    public void lowerAlbum(Long albumId) {
        //  下架
        albumIndexRepository.deleteById(albumId);
    }
}
